<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
	<head>
		<title>Phrase Options</title>
<link href="../docs-assets/Breadcrumbs.css" rel="stylesheet" rev="stylesheet" type="text/css">
		<meta name="viewport" content="width=device-width initial-scale=1">
		<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
		<meta http-equiv="Content-Language" content="en-gb">

<link href="../docs-assets/Contents.css" rel="stylesheet" rev="stylesheet" type="text/css">
<link href="../docs-assets/Progress.css" rel="stylesheet" rev="stylesheet" type="text/css">
<link href="../docs-assets/Navigation.css" rel="stylesheet" rev="stylesheet" type="text/css">
<link href="../docs-assets/Fonts.css" rel="stylesheet" rev="stylesheet" type="text/css">
<link href="../docs-assets/Base.css" rel="stylesheet" rev="stylesheet" type="text/css">
<script>
function togglePopup(material_id) {
  var popup = document.getElementById(material_id);
  popup.classList.toggle("show");
}
</script>

<link href="../docs-assets/Popups.css" rel="stylesheet" rev="stylesheet" type="text/css">
<link href="../docs-assets/Colours.css" rel="stylesheet" rev="stylesheet" type="text/css">
		
	</head>
	<body class="commentary-font">
		<nav role="navigation">
		<h1><a href="../index.html"><img src="../docs-assets/Inform.png" height=72> </a></h1>
<ul><li><a href="../index.html">home</a></li>
</ul><h2>Compiler</h2><ul>
<li><a href="../structure.html">structure</a></li>
<li><a href="../inbuildn.html">inbuild</a></li>
<li><a href="../inform7n.html">inform7</a></li>
<li><a href="../intern.html">inter</a></li>
<li><a href="../services.html">services</a></li>
<li><a href="../secrets.html">secrets</a></li>
</ul><h2>Other Tools</h2><ul>
<li><a href="../inblorbn.html">inblorb</a></li>
<li><a href="../inform6.html">inform6</a></li>
<li><a href="../inpolicyn.html">inpolicy</a></li>
</ul><h2>Resources</h2><ul>
<li><a href="../extensions.html">extensions</a></li>
<li><a href="../kits.html">kits</a></li>
</ul><h2>Repository</h2><ul>
<li><a href="https://github.com/ganelson/inform"><img src="../docs-assets/github.png" height=0> github</a></li>
</ul><h2>Related Projects</h2><ul>
<li><a href="https://github.com/ganelson/inweb"><img src="../docs-assets/github.png" height=0> inweb</a></li>
<li><a href="https://github.com/ganelson/intest"><img src="../docs-assets/github.png" height=0> intest</a></li>
</ul>
		</nav>
		<main role="main">
		<!-- Weave of 'Phrase Options' generated by inweb -->
<div class="breadcrumbs">
    <ul class="crumbs"><li><a href="../index.html">Home</a></li><li><a href="../inform7n.html">Inform7</a></li><li><a href="index.html">assertions</a></li><li><a href="index.html#5">Chapter 5: Imperative Code</a></li><li><b>Phrase Options</b></li></ul></div>
<p class="purpose">To create and subsequently parse against the list of phrase options with which the user can choose to invoke a To phrase.</p>

<ul class="toc"><li><a href="5-po.html#SP1">&#167;1. Introduction</a></li><li><a href="5-po.html#SP2">&#167;2. Creation</a></li><li><a href="5-po.html#SP4">&#167;4. Parsing</a></li><li><a href="5-po.html#SP6">&#167;6. Parsing phrase options in a declaration</a></li><li><a href="5-po.html#SP8">&#167;8. Parsing phrase options in an invocation</a></li></ul><hr class="tocbar">

<p class="commentary firstcommentary"><a id="SP1" class="paragraph-anchor"></a><b>&#167;1. Introduction.</b>A "phrase option" is a sort of modifier tacked on to an invocation of a
phrase; the only modifiers allowed are those declared in that phrase's
preamble. Phrase options are an early feature of Inform 7 going back to a
time when its priority was to enable the paraphrasing of Inform 6 library
features (such as the bitmap passed as a parameter to the list-printer).
</p>

<p class="commentary">I now slightly regret the existence of phrase options, but above all the
comma-based syntax used for them, as here. Brackets would have been better;
it makes phrase options impossible to use for text substitutions.
</p>

<blockquote>
    <p>let R be the best route from X to Y, using doors;</p>
</blockquote>

<p class="commentary">I sometimes even regret the existence of phrase options, but it must be
admitted that they are a clean way to interface to low-level Inform 6 code.
But it's mostly the comma which annoys me (making text substitutions unable
to support phrase options); I should have gone for brackets.
</p>

<p class="commentary">The <a href="5-po.html#SP1" class="internal">id_options_data</a> for an imperative definition, which is part of its
type data, says what options it allows:
</p>

<pre class="definitions code-font"><span class="definition-keyword">define</span> <span class="constant-syntax">MAX_OPTIONS_PER_PHRASE</span><span class="plain-syntax"> </span><span class="constant-syntax">16</span><span class="plain-syntax"> </span><span class="comment-syntax"> because held in a 16-bit Z-machine bitmap</span>
</pre>
<pre class="displayed-code all-displayed-code code-font">
<span class="reserved-syntax">typedef</span><span class="plain-syntax"> </span><span class="reserved-syntax">struct</span><span class="plain-syntax"> </span><span class="reserved-syntax">id_options_data</span><span class="plain-syntax"> {</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">struct</span><span class="plain-syntax"> </span><span class="reserved-syntax">phrase_option</span><span class="plain-syntax"> *</span><span class="identifier-syntax">options_permitted</span><span class="plain-syntax">[</span><span class="constant-syntax">MAX_OPTIONS_PER_PHRASE</span><span class="plain-syntax">];</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">no_options_permitted</span><span class="plain-syntax">;</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">struct</span><span class="plain-syntax"> </span><span class="identifier-syntax">wording</span><span class="plain-syntax"> </span><span class="identifier-syntax">options_declaration</span><span class="plain-syntax">; </span><span class="comment-syntax"> the text declaring the whole set of options</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">multiple_options_permitted</span><span class="plain-syntax">; </span><span class="comment-syntax"> can be combined, or mutually exclusive?</span>
<span class="plain-syntax">} </span><span class="reserved-syntax">id_options_data</span><span class="plain-syntax">;</span>

<span class="reserved-syntax">typedef</span><span class="plain-syntax"> </span><span class="reserved-syntax">struct</span><span class="plain-syntax"> </span><span class="reserved-syntax">phrase_option</span><span class="plain-syntax"> {</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">struct</span><span class="plain-syntax"> </span><span class="identifier-syntax">wording</span><span class="plain-syntax"> </span><span class="identifier-syntax">name</span><span class="plain-syntax">; </span><span class="comment-syntax"> text of name</span>
<span class="plain-syntax">} </span><span class="reserved-syntax">phrase_option</span><span class="plain-syntax">;</span>
</pre>
<ul class="endnotetexts"><li>The structure id_options_data is private to this section.</li><li>The structure phrase_option is accessed in 3/nuor, 3/dbtr, 3/rpr, 4/ass, 5/tpf, 6/rls, 6/fao, 6/act, 6/sv, 7/tc, 7/tbl, 7/eqt and here.</li></ul>
<p class="commentary firstcommentary"><a id="SP2" class="paragraph-anchor"></a><b>&#167;2. Creation.</b>By default, a phrase has no options.
</p>

<pre class="displayed-code all-displayed-code code-font">
<span class="reserved-syntax">id_options_data</span><span class="plain-syntax"> </span><span class="function-syntax">PhraseOptions::new</span><button class="popup" onclick="togglePopup('usagePopup1')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup1">Usage of <span class="code-font"><span class="function-syntax">PhraseOptions::new</span></span>:<br/>Phrase Type Data - <a href="5-ptd.html#SP2">&#167;2</a></span></button><span class="plain-syntax">(</span><span class="identifier-syntax">wording</span><span class="plain-syntax"> </span><span class="identifier-syntax">W</span><span class="plain-syntax">) {</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">id_options_data</span><span class="plain-syntax"> </span><span class="identifier-syntax">phod</span><span class="plain-syntax">;</span>
<span class="plain-syntax">    </span><span class="identifier-syntax">phod</span><span class="plain-syntax">.</span><span class="element-syntax">no_options_permitted</span><span class="plain-syntax"> = </span><span class="constant-syntax">0</span><span class="plain-syntax">;</span>
<span class="plain-syntax">    </span><span class="identifier-syntax">phod</span><span class="plain-syntax">.</span><span class="element-syntax">multiple_options_permitted</span><span class="plain-syntax"> = </span><span class="identifier-syntax">FALSE</span><span class="plain-syntax">;</span>
<span class="plain-syntax">    </span><span class="identifier-syntax">phod</span><span class="plain-syntax">.</span><span class="element-syntax">options_declaration</span><span class="plain-syntax"> = </span><span class="identifier-syntax">W</span><span class="plain-syntax">;</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">phod</span><span class="plain-syntax">;</span>
<span class="plain-syntax">}</span>

<span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="function-syntax">PhraseOptions::allows_options</span><span class="plain-syntax">(</span><span class="reserved-syntax">id_body</span><span class="plain-syntax"> *</span><span class="identifier-syntax">idb</span><span class="plain-syntax">) {</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">id_options_data</span><span class="plain-syntax"> *</span><span class="identifier-syntax">phod</span><span class="plain-syntax"> = &amp;(</span><span class="identifier-syntax">idb</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">type_data</span><span class="plain-syntax">.</span><span class="element-syntax">options_data</span><span class="plain-syntax">);</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">phod</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">no_options_permitted</span><span class="plain-syntax"> &gt; </span><span class="constant-syntax">0</span><span class="plain-syntax">) </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">TRUE</span><span class="plain-syntax">;</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">FALSE</span><span class="plain-syntax">;</span>
<span class="plain-syntax">}</span>
</pre>
<p class="commentary firstcommentary"><a id="SP3" class="paragraph-anchor"></a><b>&#167;3. </b></p>

<pre class="displayed-code all-displayed-code code-font">
<span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">PM_TooManyPhraseOptions_issued</span><span class="plain-syntax"> = </span><span class="identifier-syntax">FALSE</span><span class="plain-syntax">;</span>
<span class="reserved-syntax">void</span><span class="plain-syntax"> </span><span class="function-syntax">PhraseOptions::phod_add_phrase_option</span><button class="popup" onclick="togglePopup('usagePopup2')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup2">Usage of <span class="code-font"><span class="function-syntax">PhraseOptions::phod_add_phrase_option</span></span>:<br/><a href="5-po.html#SP7_1">&#167;7.1</a></span></button><span class="plain-syntax">(</span><span class="reserved-syntax">id_options_data</span><span class="plain-syntax"> *</span><span class="identifier-syntax">phod</span><span class="plain-syntax">, </span><span class="identifier-syntax">wording</span><span class="plain-syntax"> </span><span class="identifier-syntax">W</span><span class="plain-syntax">) {</span>
<span class="plain-syntax">    </span><span class="identifier-syntax">LOGIF</span><span class="plain-syntax">(</span><span class="identifier-syntax">PHRASE_CREATIONS</span><span class="plain-syntax">, </span><span class="string-syntax">"Adding phrase option &lt;%W&gt;\n"</span><span class="plain-syntax">, </span><span class="identifier-syntax">W</span><span class="plain-syntax">);</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">phod</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">no_options_permitted</span><span class="plain-syntax"> &gt;= </span><span class="constant-syntax">MAX_OPTIONS_PER_PHRASE</span><span class="plain-syntax">) {</span>
<span class="plain-syntax">        </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">PM_TooManyPhraseOptions_issued</span><span class="plain-syntax"> == </span><span class="identifier-syntax">FALSE</span><span class="plain-syntax">)</span>
<span class="plain-syntax">            </span><span class="identifier-syntax">StandardProblems::sentence_problem</span><span class="plain-syntax">(</span><span class="identifier-syntax">Task::syntax_tree</span><span class="plain-syntax">(),</span>
<span class="plain-syntax">                </span><span class="identifier-syntax">_p_</span><span class="plain-syntax">(</span><span class="identifier-syntax">PM_TooManyPhraseOptions</span><span class="plain-syntax">),</span>
<span class="plain-syntax">                </span><span class="string-syntax">"a phrase is only allowed to have 16 different options"</span><span class="plain-syntax">,</span>
<span class="plain-syntax">                </span><span class="string-syntax">"so either some of these will need to go, or you may want to consider "</span>
<span class="plain-syntax">                </span><span class="string-syntax">"breaking up the phrase into simpler ones whose usage is easier to describe."</span><span class="plain-syntax">);</span>
<span class="plain-syntax">        </span><span class="identifier-syntax">PM_TooManyPhraseOptions_issued</span><span class="plain-syntax"> = </span><span class="identifier-syntax">TRUE</span><span class="plain-syntax">;</span>
<span class="plain-syntax">        </span><span class="reserved-syntax">return</span><span class="plain-syntax">;</span>
<span class="plain-syntax">    }</span>
<span class="plain-syntax">    </span><span class="identifier-syntax">PM_TooManyPhraseOptions_issued</span><span class="plain-syntax"> = </span><span class="identifier-syntax">FALSE</span><span class="plain-syntax">; </span><span class="comment-syntax"> so the problem can recur on later phrases</span>

<span class="plain-syntax">    </span><span class="reserved-syntax">phrase_option</span><span class="plain-syntax"> *</span><span class="identifier-syntax">po</span><span class="plain-syntax"> = </span><span class="identifier-syntax">CREATE</span><span class="plain-syntax">(</span><span class="reserved-syntax">phrase_option</span><span class="plain-syntax">);</span>
<span class="plain-syntax">    </span><span class="identifier-syntax">po</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">name</span><span class="plain-syntax"> = </span><span class="identifier-syntax">W</span><span class="plain-syntax">;</span>
<span class="plain-syntax">    </span><span class="identifier-syntax">phod</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">options_permitted</span><span class="plain-syntax">[</span><span class="identifier-syntax">phod</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">no_options_permitted</span><span class="plain-syntax">++] = </span><span class="identifier-syntax">po</span><span class="plain-syntax">;</span>
<span class="plain-syntax">}</span>
</pre>
<p class="commentary firstcommentary"><a id="SP4" class="paragraph-anchor"></a><b>&#167;4. Parsing.</b>This isn't very efficient, but doesn't need to be, since phrase options are parsed
only in a condition context, not in a value context, and these are relatively
rare in Inform source text.
</p>

<pre class="displayed-code all-displayed-code code-font">
<span class="reserved-syntax">id_options_data</span><span class="plain-syntax"> *</span><span class="identifier-syntax">phod_being_parsed</span><span class="plain-syntax"> = </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">;</span>
<span class="reserved-syntax">id_body</span><span class="plain-syntax"> *</span><span class="identifier-syntax">idb_being_parsed</span><span class="plain-syntax"> = </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">;</span>

<span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="function-syntax">PhraseOptions::parse_phod</span><button class="popup" onclick="togglePopup('usagePopup3')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup3">Usage of <span class="code-font"><span class="function-syntax">PhraseOptions::parse_phod</span></span>:<br/><a href="5-po.html#SP5">&#167;5</a></span></button><span class="plain-syntax">(</span><span class="reserved-syntax">id_options_data</span><span class="plain-syntax"> *</span><span class="identifier-syntax">phod</span><span class="plain-syntax">, </span><span class="identifier-syntax">wording</span><span class="plain-syntax"> </span><span class="identifier-syntax">W</span><span class="plain-syntax">) {</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">for</span><span class="plain-syntax"> (</span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">i</span><span class="plain-syntax"> = </span><span class="constant-syntax">0</span><span class="plain-syntax">; </span><span class="identifier-syntax">i</span><span class="plain-syntax"> &lt; </span><span class="identifier-syntax">phod</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">no_options_permitted</span><span class="plain-syntax">; </span><span class="identifier-syntax">i</span><span class="plain-syntax">++)</span>
<span class="plain-syntax">        </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">Wordings::match</span><span class="plain-syntax">(</span><span class="identifier-syntax">W</span><span class="plain-syntax">, </span><span class="identifier-syntax">phod</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">options_permitted</span><span class="plain-syntax">[</span><span class="identifier-syntax">i</span><span class="plain-syntax">]-&gt;</span><span class="element-syntax">name</span><span class="plain-syntax">))</span>
<span class="plain-syntax">            </span><span class="reserved-syntax">return</span><span class="plain-syntax"> (1 &lt;&lt; </span><span class="identifier-syntax">i</span><span class="plain-syntax">);</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">return</span><span class="plain-syntax"> -1;</span>
<span class="plain-syntax">}</span>
<span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="function-syntax">PhraseOptions::parse</span><span class="plain-syntax">(</span><span class="reserved-syntax">id_body</span><span class="plain-syntax"> *</span><span class="identifier-syntax">idb</span><span class="plain-syntax">, </span><span class="identifier-syntax">wording</span><span class="plain-syntax"> </span><span class="identifier-syntax">W</span><span class="plain-syntax">) {</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><a href="5-po.html#SP4" class="function-link"><span class="function-syntax">PhraseOptions::parse_phod</span></a><span class="plain-syntax">(&amp;(</span><span class="identifier-syntax">idb</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">type_data</span><span class="plain-syntax">.</span><span class="element-syntax">options_data</span><span class="plain-syntax">), </span><span class="identifier-syntax">W</span><span class="plain-syntax">);</span>
<span class="plain-syntax">}</span>
</pre>
<p class="commentary firstcommentary"><a id="SP5" class="paragraph-anchor"></a><b>&#167;5. </b>Which we wrap up thus:
</p>

<pre class="displayed-code all-displayed-code code-font">
<span class="function-syntax">&lt;phrase-option&gt;</span><span class="plain-syntax"> </span><span class="identifier-syntax">internal</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">bitmap</span><span class="plain-syntax"> = </span><a href="5-po.html#SP4" class="function-link"><span class="function-syntax">PhraseOptions::parse_phod</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">phod_being_parsed</span><span class="plain-syntax">, </span><span class="identifier-syntax">W</span><span class="plain-syntax">);</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">bitmap</span><span class="plain-syntax"> == -1) { ==&gt; { </span><span class="identifier-syntax">fail</span><span class="plain-syntax"> </span><span class="identifier-syntax">nonterminal</span><span class="plain-syntax"> }; }</span>
<span class="plain-syntax">    ==&gt; { </span><span class="identifier-syntax">bitmap</span><span class="plain-syntax">, - };</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">TRUE</span><span class="plain-syntax">;</span>
<span class="plain-syntax">}</span>
</pre>
<p class="commentary firstcommentary"><a id="SP6" class="paragraph-anchor"></a><b>&#167;6. Parsing phrase options in a declaration.</b>The following is called with <span class="extract"><span class="extract-syntax">W</span></span> set to just the part of a phrase prototype
containing its phrase options. In this example:
</p>

<pre class="displayed-code all-displayed-code code-font">
<span class="identifier-syntax">To</span><span class="plain-syntax"> </span><span class="identifier-syntax">decide</span><span class="plain-syntax"> </span><span class="identifier-syntax">which</span><span class="plain-syntax"> </span><span class="identifier-syntax">object</span><span class="plain-syntax"> </span><span class="identifier-syntax">is</span><span class="plain-syntax"> </span><span class="identifier-syntax">best</span><span class="plain-syntax"> </span><span class="identifier-syntax">route</span><span class="plain-syntax"> </span><span class="identifier-syntax">from</span><span class="plain-syntax"> (</span><span class="identifier-syntax">R1</span><span class="plain-syntax"> - </span><span class="identifier-syntax">object</span><span class="plain-syntax">) </span><span class="identifier-syntax">to</span><span class="plain-syntax"> (</span><span class="identifier-syntax">R2</span><span class="plain-syntax"> - </span><span class="identifier-syntax">object</span><span class="plain-syntax">),</span>
<span class="plain-syntax">    </span><span class="identifier-syntax">using</span><span class="plain-syntax"> </span><span class="identifier-syntax">doors</span><span class="plain-syntax"> </span><span class="identifier-syntax">or</span><span class="plain-syntax"> </span><span class="identifier-syntax">using</span><span class="plain-syntax"> </span><span class="identifier-syntax">even</span><span class="plain-syntax"> </span><span class="identifier-syntax">locked</span><span class="plain-syntax"> </span><span class="identifier-syntax">doors</span><span class="plain-syntax">:</span>
</pre>
<p class="commentary"><span class="extract"><span class="extract-syntax">W</span></span> would be "using doors or using even locked doors".
</p>

<p class="commentary">The syntax is just a list of names, but with the wrinkle that if the list is divided
with "or" then the options are mutually exclusive, but with "and/or" they're not.
</p>

<pre class="displayed-code all-displayed-code code-font">
<span class="reserved-syntax">void</span><span class="plain-syntax"> </span><span class="function-syntax">PhraseOptions::parse_declared_options</span><button class="popup" onclick="togglePopup('usagePopup4')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup4">Usage of <span class="code-font"><span class="function-syntax">PhraseOptions::parse_declared_options</span></span>:<br/>Parsing Type Data - <a href="5-ptd2.html#SP1">&#167;1</a></span></button><span class="plain-syntax">(</span><span class="reserved-syntax">id_options_data</span><span class="plain-syntax"> *</span><span class="identifier-syntax">phod</span><span class="plain-syntax">, </span><span class="identifier-syntax">wording</span><span class="plain-syntax"> </span><span class="identifier-syntax">W</span><span class="plain-syntax">) {</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">Wordings::nonempty</span><span class="plain-syntax">(</span><span class="identifier-syntax">W</span><span class="plain-syntax">)) {</span>
<span class="plain-syntax">        </span><span class="identifier-syntax">phod</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">options_declaration</span><span class="plain-syntax"> = </span><span class="identifier-syntax">W</span><span class="plain-syntax">;</span>
<span class="plain-syntax">        </span><span class="identifier-syntax">phod_being_parsed</span><span class="plain-syntax"> = </span><span class="identifier-syntax">phod</span><span class="plain-syntax">;</span>
<span class="plain-syntax">        </span><span class="function-syntax">&lt;phrase-option-decl-list&gt;</span><span class="plain-syntax">(</span><span class="identifier-syntax">W</span><span class="plain-syntax">);</span>
<span class="plain-syntax">        </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="function-syntax">&lt;&lt;r&gt;&gt;</span><span class="plain-syntax">) </span><span class="identifier-syntax">phod</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">multiple_options_permitted</span><span class="plain-syntax"> = </span><span class="identifier-syntax">TRUE</span><span class="plain-syntax">;</span>
<span class="plain-syntax">    }</span>
<span class="plain-syntax">}</span>
</pre>
<p class="commentary firstcommentary"><a id="SP7" class="paragraph-anchor"></a><b>&#167;7. </b>Note the following Preform grammar passes the return value <span class="extract"><span class="extract-syntax">TRUE</span></span> up from
the final element of the list when the connective used for it was "and/or".
Note also the rare use of the Preform literal marker in <span class="extract"><span class="extract-syntax">\and/or</span></span> to show
that the slash between "and" and "or" is part of the word.
</p>

<pre class="displayed-code all-displayed-code code-font">
<span class="function-syntax">&lt;phrase-option-decl-list&gt;</span>
<span class="plain-syntax">    ... |</span>
<span class="plain-syntax">    </span><span class="function-syntax">&lt;phrase-option-decl-setting-entry&gt;</span><span class="plain-syntax"> </span><span class="function-syntax">&lt;phrase-option-decl-tail&gt;</span><span class="plain-syntax"> |</span>
<span class="plain-syntax">    </span><span class="function-syntax">&lt;phrase-option-decl-setting-entry&gt;</span>

<span class="function-syntax">&lt;phrase-option-decl-tail&gt;</span>
<span class="plain-syntax">    , </span><span class="identifier-syntax">_or</span><span class="plain-syntax"> </span><span class="function-syntax">&lt;phrase-option-decl-list&gt;</span><span class="plain-syntax"> |</span>
<span class="plain-syntax">    , \</span><span class="identifier-syntax">and</span><span class="plain-syntax">/</span><span class="identifier-syntax">or</span><span class="plain-syntax"> </span><span class="function-syntax">&lt;phrase-option-decl-list&gt;</span><span class="plain-syntax"> |</span>
<span class="plain-syntax">    </span><span class="identifier-syntax">_</span><span class="plain-syntax">,/</span><span class="identifier-syntax">or</span><span class="plain-syntax"> </span><span class="function-syntax">&lt;phrase-option-decl-list&gt;</span><span class="plain-syntax"> |</span>
<span class="plain-syntax">    \</span><span class="identifier-syntax">and</span><span class="plain-syntax">/</span><span class="identifier-syntax">or</span><span class="plain-syntax"> </span><span class="function-syntax">&lt;phrase-option-decl-list&gt;</span>

<span class="function-syntax">&lt;phrase-option-decl-setting-entry&gt;</span>
<span class="plain-syntax">    ... |</span>
<span class="plain-syntax">    ...</span>
</pre>
<p class="commentary firstcommentary"><a id="SP7_1" class="paragraph-anchor"></a><b>&#167;7.1. </b><span class="named-paragraph-container code-font"><span class="named-paragraph-defn">Add a phrase option</span><span class="named-paragraph-number">7.1</span></span><span class="comment-syntax"> =</span>
</p>

<pre class="displayed-code all-displayed-code code-font">
<span class="plain-syntax">    </span><a href="5-po.html#SP3" class="function-link"><span class="function-syntax">PhraseOptions::phod_add_phrase_option</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">phod_being_parsed</span><span class="plain-syntax">, </span><span class="identifier-syntax">W</span><span class="plain-syntax">);</span>
<span class="plain-syntax">    ==&gt; { </span><span class="identifier-syntax">FALSE</span><span class="plain-syntax">, - };</span>
</pre>
<ul class="endnotetexts"><li>This code is used in <a href="5-po.html#SP7">&#167;7</a>.</li></ul>
<p class="commentary firstcommentary"><a id="SP8" class="paragraph-anchor"></a><b>&#167;8. Parsing phrase options in an invocation.</b>At this point, we're looking at the text after the first comma in something
like:
</p>

<blockquote>
    <p>list the contents of the box, as a sentence, with newlines;</p>
</blockquote>

<p class="commentary">The invocation has already been parsed enough that we know the options
chosen are:
</p>

<blockquote>
    <p>as a sentence, with newlines</p>
</blockquote>

<p class="commentary">and the following routine turns that into a bitmap with two bits set, one
corresponding to each choice.
</p>

<p class="commentary">We return <span class="extract"><span class="extract-syntax">TRUE</span></span> or <span class="extract"><span class="extract-syntax">FALSE</span></span> according to whether the options were valid or
not, and the <span class="extract"><span class="extract-syntax">silently</span></span> flag suppresses problem messages we would otherwise
produce.
</p>

<pre class="displayed-code all-displayed-code code-font">
<span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">phod_being_parsed_silently</span><span class="plain-syntax"> = </span><span class="identifier-syntax">FALSE</span><span class="plain-syntax">; </span><span class="comment-syntax"> context for the grammar below</span>

<span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="function-syntax">PhraseOptions::parse_invoked_options</span><span class="plain-syntax">(</span><span class="identifier-syntax">parse_node</span><span class="plain-syntax"> *</span><span class="identifier-syntax">inv</span><span class="plain-syntax">, </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">silently</span><span class="plain-syntax">) {</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">id_body</span><span class="plain-syntax"> *</span><span class="identifier-syntax">idb</span><span class="plain-syntax"> = </span><span class="identifier-syntax">Node::get_phrase_invoked</span><span class="plain-syntax">(</span><span class="identifier-syntax">inv</span><span class="plain-syntax">);</span>
<span class="plain-syntax">    </span><span class="identifier-syntax">wording</span><span class="plain-syntax"> </span><span class="identifier-syntax">W</span><span class="plain-syntax"> = </span><span class="identifier-syntax">Invocations::get_phrase_options</span><span class="plain-syntax">(</span><span class="identifier-syntax">inv</span><span class="plain-syntax">);</span>

<span class="plain-syntax">    </span><span class="identifier-syntax">idb_being_parsed</span><span class="plain-syntax"> = </span><span class="identifier-syntax">idb</span><span class="plain-syntax">;</span>
<span class="plain-syntax">    </span><span class="identifier-syntax">phod_being_parsed</span><span class="plain-syntax"> = &amp;(</span><span class="identifier-syntax">idb_being_parsed</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">type_data</span><span class="plain-syntax">.</span><span class="element-syntax">options_data</span><span class="plain-syntax">);</span>

<span class="plain-syntax">    </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">bitmap</span><span class="plain-syntax"> = </span><span class="constant-syntax">0</span><span class="plain-syntax">;</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">pc</span><span class="plain-syntax"> = </span><span class="identifier-syntax">problem_count</span><span class="plain-syntax">;</span>
<span class="plain-syntax">    </span><span class="named-paragraph-container code-font"><a href="5-po.html#SP8_1" class="named-paragraph-link"><span class="named-paragraph">Parse the supplied list of options into a bitmap</span><span class="named-paragraph-number">8.1</span></a></span><span class="plain-syntax">;</span>

<span class="plain-syntax">    </span><span class="identifier-syntax">Invocations::set_phrase_options_bitmap</span><span class="plain-syntax">(</span><span class="identifier-syntax">inv</span><span class="plain-syntax">, </span><span class="identifier-syntax">bitmap</span><span class="plain-syntax">);</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">problem_count</span><span class="plain-syntax"> &gt; </span><span class="identifier-syntax">pc</span><span class="plain-syntax">) </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">FALSE</span><span class="plain-syntax">;</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">TRUE</span><span class="plain-syntax">;</span>
<span class="plain-syntax">}</span>
</pre>
<p class="commentary firstcommentary"><a id="SP8_1" class="paragraph-anchor"></a><b>&#167;8.1. </b><span class="named-paragraph-container code-font"><span class="named-paragraph-defn">Parse the supplied list of options into a bitmap</span><span class="named-paragraph-number">8.1</span></span><span class="comment-syntax"> =</span>
</p>

<pre class="displayed-code all-displayed-code code-font">
<span class="plain-syntax">    </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">s</span><span class="plain-syntax"> = </span><span class="identifier-syntax">phod_being_parsed_silently</span><span class="plain-syntax">;</span>
<span class="plain-syntax">    </span><span class="identifier-syntax">phod_being_parsed_silently</span><span class="plain-syntax"> = </span><span class="identifier-syntax">silently</span><span class="plain-syntax">;</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="function-syntax">&lt;phrase-option-list&gt;</span><span class="plain-syntax">(</span><span class="identifier-syntax">W</span><span class="plain-syntax">)) </span><span class="identifier-syntax">bitmap</span><span class="plain-syntax"> = </span><span class="function-syntax">&lt;&lt;r&gt;&gt;</span><span class="plain-syntax">;</span>
<span class="plain-syntax">    </span><span class="identifier-syntax">phod_being_parsed_silently</span><span class="plain-syntax"> = </span><span class="identifier-syntax">s</span><span class="plain-syntax">;</span>

<span class="plain-syntax">    </span><span class="reserved-syntax">if</span><span class="plain-syntax"> ((</span><span class="identifier-syntax">problem_count</span><span class="plain-syntax"> == </span><span class="identifier-syntax">pc</span><span class="plain-syntax">) &amp;&amp;</span>
<span class="plain-syntax">        (</span><span class="identifier-syntax">phod_being_parsed</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">multiple_options_permitted</span><span class="plain-syntax"> == </span><span class="identifier-syntax">FALSE</span><span class="plain-syntax">))</span>
<span class="plain-syntax">        </span><span class="named-paragraph-container code-font"><a href="5-po.html#SP8_1_1" class="named-paragraph-link"><span class="named-paragraph">Reject this if multiple options are set</span><span class="named-paragraph-number">8.1.1</span></a></span><span class="plain-syntax">;</span>
</pre>
<ul class="endnotetexts"><li>This code is used in <a href="5-po.html#SP8">&#167;8</a>.</li></ul>
<p class="commentary firstcommentary"><a id="SP8_1_1" class="paragraph-anchor"></a><b>&#167;8.1.1. </b>Ah, bit-twiddling: fun for all the family. There's no point computing the
population count of the bitmap, that is, the number of bits set: we only need
to know if it's a power of 2 or not. Note that subtracting 1, in binary,
clears the least significant set bit, leaves the higher bits as they are,
and changes the lower bits (which were previously all 0s) to 1s. So taking
a bitwise-and of a number and itself minus one leaves just the higher bits
alone. The original number therefore had a single set bit if and only if
this residue is zero.
</p>

<p class="commentary"><span class="named-paragraph-container code-font"><span class="named-paragraph-defn">Reject this if multiple options are set</span><span class="named-paragraph-number">8.1.1</span></span><span class="comment-syntax"> =</span>
</p>

<pre class="displayed-code all-displayed-code code-font">
<span class="plain-syntax">    </span><span class="reserved-syntax">if</span><span class="plain-syntax"> ((</span><span class="identifier-syntax">bitmap</span><span class="plain-syntax"> &amp; (</span><span class="identifier-syntax">bitmap</span><span class="plain-syntax"> - </span><span class="constant-syntax">1</span><span class="plain-syntax">)) != </span><span class="constant-syntax">0</span><span class="plain-syntax">) {</span>
<span class="plain-syntax">        </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">silently</span><span class="plain-syntax"> == </span><span class="identifier-syntax">FALSE</span><span class="plain-syntax">) {</span>
<span class="plain-syntax">            </span><span class="identifier-syntax">Problems::quote_source</span><span class="plain-syntax">(1, </span><span class="identifier-syntax">current_sentence</span><span class="plain-syntax">);</span>
<span class="plain-syntax">            </span><span class="identifier-syntax">Problems::quote_wording</span><span class="plain-syntax">(2, </span><span class="identifier-syntax">W</span><span class="plain-syntax">);</span>
<span class="plain-syntax">            </span><span class="identifier-syntax">Problems::quote_phrase</span><span class="plain-syntax">(3, </span><span class="identifier-syntax">idb</span><span class="plain-syntax">);</span>
<span class="plain-syntax">            </span><span class="identifier-syntax">Problems::quote_wording</span><span class="plain-syntax">(4, </span><span class="identifier-syntax">phod_being_parsed</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">options_declaration</span><span class="plain-syntax">);</span>
<span class="plain-syntax">            </span><span class="identifier-syntax">StandardProblems::handmade_problem</span><span class="plain-syntax">(</span><span class="identifier-syntax">Task::syntax_tree</span><span class="plain-syntax">(),</span>
<span class="plain-syntax">                </span><span class="identifier-syntax">_p_</span><span class="plain-syntax">(</span><span class="identifier-syntax">PM_PhraseOptionsExclusive</span><span class="plain-syntax">));</span>
<span class="plain-syntax">            </span><span class="identifier-syntax">Problems::issue_problem_segment</span><span class="plain-syntax">(</span>
<span class="plain-syntax">                </span><span class="string-syntax">"You wrote %1, supplying the options '%2' to the phrase '%3', but "</span>
<span class="plain-syntax">                </span><span class="string-syntax">"the options listed for this phrase ('%4') are mutually exclusive."</span><span class="plain-syntax">);</span>
<span class="plain-syntax">            </span><span class="identifier-syntax">Problems::issue_problem_end</span><span class="plain-syntax">();</span>
<span class="plain-syntax">        }</span>
<span class="plain-syntax">        </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">FALSE</span><span class="plain-syntax">;</span>
<span class="plain-syntax">    }</span>
</pre>
<ul class="endnotetexts"><li>This code is used in <a href="5-po.html#SP8_1">&#167;8.1</a>.</li></ul>
<p class="commentary firstcommentary"><a id="SP9" class="paragraph-anchor"></a><b>&#167;9. </b>When setting options, in an actual use of a phrase, the list is divided
by "and":
</p>

<pre class="displayed-code all-displayed-code code-font">
<span class="function-syntax">&lt;phrase-option-list&gt;</span>
<span class="plain-syntax">    ... |</span>
<span class="plain-syntax">    </span><span class="function-syntax">&lt;phrase-option-setting-entry&gt;</span><span class="plain-syntax"> </span><span class="function-syntax">&lt;phrase-option-tail&gt;</span><span class="plain-syntax"> |</span>
<span class="plain-syntax">    </span><span class="function-syntax">&lt;phrase-option-setting-entry&gt;</span>

<span class="function-syntax">&lt;phrase-option-tail&gt;</span>
<span class="plain-syntax">    , </span><span class="identifier-syntax">_and</span><span class="plain-syntax"> </span><span class="function-syntax">&lt;phrase-option-list&gt;</span><span class="plain-syntax"> |</span>
<span class="plain-syntax">    </span><span class="identifier-syntax">_</span><span class="plain-syntax">,/</span><span class="identifier-syntax">and</span><span class="plain-syntax"> </span><span class="function-syntax">&lt;phrase-option-list&gt;</span>

<span class="function-syntax">&lt;phrase-option-setting-entry&gt;</span>
<span class="plain-syntax">    </span><span class="function-syntax">&lt;phrase-option&gt;</span><span class="plain-syntax"> |</span>
<span class="plain-syntax">    ...</span>
</pre>
<p class="commentary firstcommentary"><a id="SP9_1" class="paragraph-anchor"></a><b>&#167;9.1. </b><span class="named-paragraph-container code-font"><span class="named-paragraph-defn">Issue PM_NotAPhraseOption or C22NotTheOnlyPhraseOption problem</span><span class="named-paragraph-number">9.1</span></span><span class="comment-syntax"> =</span>
</p>

<pre class="displayed-code all-displayed-code code-font">
<span class="plain-syntax">    </span><span class="reserved-syntax">if</span><span class="plain-syntax"> ((!</span><span class="identifier-syntax">preform_lookahead_mode</span><span class="plain-syntax">) &amp;&amp; (!</span><span class="identifier-syntax">phod_being_parsed_silently</span><span class="plain-syntax">)) {</span>
<span class="plain-syntax">        </span><span class="identifier-syntax">Problems::quote_source</span><span class="plain-syntax">(1, </span><span class="identifier-syntax">current_sentence</span><span class="plain-syntax">);</span>
<span class="plain-syntax">        </span><span class="identifier-syntax">Problems::quote_wording</span><span class="plain-syntax">(2, </span><span class="identifier-syntax">W</span><span class="plain-syntax">);</span>
<span class="plain-syntax">        </span><span class="identifier-syntax">Problems::quote_phrase</span><span class="plain-syntax">(3, </span><span class="identifier-syntax">idb_being_parsed</span><span class="plain-syntax">);</span>
<span class="plain-syntax">        </span><span class="identifier-syntax">Problems::quote_wording</span><span class="plain-syntax">(4, </span><span class="identifier-syntax">phod_being_parsed</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">options_declaration</span><span class="plain-syntax">);</span>
<span class="plain-syntax">        </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">phod_being_parsed</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">no_options_permitted</span><span class="plain-syntax"> &gt; </span><span class="constant-syntax">1</span><span class="plain-syntax">) {</span>
<span class="plain-syntax">            </span><span class="identifier-syntax">StandardProblems::handmade_problem</span><span class="plain-syntax">(</span><span class="identifier-syntax">Task::syntax_tree</span><span class="plain-syntax">(),</span>
<span class="plain-syntax">                </span><span class="identifier-syntax">_p_</span><span class="plain-syntax">(</span><span class="identifier-syntax">PM_NotAPhraseOption</span><span class="plain-syntax">));</span>
<span class="plain-syntax">            </span><span class="identifier-syntax">Problems::issue_problem_segment</span><span class="plain-syntax">(</span>
<span class="plain-syntax">                </span><span class="string-syntax">"You wrote %1, but '%2' is not one of the options allowed on "</span>
<span class="plain-syntax">                </span><span class="string-syntax">"the end of the phrase '%3'. (The options allowed are: '%4'.)"</span><span class="plain-syntax">);</span>
<span class="plain-syntax">            </span><span class="identifier-syntax">Problems::issue_problem_end</span><span class="plain-syntax">();</span>
<span class="plain-syntax">        } </span><span class="reserved-syntax">else</span><span class="plain-syntax"> {</span>
<span class="plain-syntax">            </span><span class="identifier-syntax">StandardProblems::handmade_problem</span><span class="plain-syntax">(</span><span class="identifier-syntax">Task::syntax_tree</span><span class="plain-syntax">(),</span>
<span class="plain-syntax">                </span><span class="identifier-syntax">_p_</span><span class="plain-syntax">(</span><span class="identifier-syntax">PM_NotTheOnlyPhraseOption</span><span class="plain-syntax">));</span>
<span class="plain-syntax">            </span><span class="identifier-syntax">Problems::issue_problem_segment</span><span class="plain-syntax">(</span>
<span class="plain-syntax">                </span><span class="string-syntax">"You wrote %1, but the only option allowed on the end of the "</span>
<span class="plain-syntax">                </span><span class="string-syntax">"phrase '%3' is '%4', so '%2' is not something I know how to "</span>
<span class="plain-syntax">                </span><span class="string-syntax">"deal with."</span><span class="plain-syntax">);</span>
<span class="plain-syntax">            </span><span class="identifier-syntax">Problems::issue_problem_end</span><span class="plain-syntax">();</span>
<span class="plain-syntax">        }</span>
<span class="plain-syntax">    }</span>
</pre>
<ul class="endnotetexts"><li>This code is used in <a href="5-po.html#SP9">&#167;9</a>.</li></ul>
<nav role="progress"><div class="progresscontainer">
    <ul class="progressbar"><li class="progressprev"><a href="5-ptd2.html">&#10094;</a></li><li class="progresschapter"><a href="P-wtmd.html">P</a></li><li class="progresschapter"><a href="1-am.html">1</a></li><li class="progresschapter"><a href="2-bv.html">2</a></li><li class="progresschapter"><a href="3-dlr.html">3</a></li><li class="progresschapter"><a href="4-nr.html">4</a></li><li class="progresscurrentchapter">5</li><li class="progresssection"><a href="5-id.html">id</a></li><li class="progresssection"><a href="5-idf.html">idf</a></li><li class="progresssection"><a href="5-adf.html">adf</a></li><li class="progresssection"><a href="5-tpf.html">tpf</a></li><li class="progresssection"><a href="5-ptd.html">ptd</a></li><li class="progresssection"><a href="5-ptd2.html">ptd2</a></li><li class="progresscurrent">po</li><li class="progresssection"><a href="5-rf.html">rf</a></li><li class="progresssection"><a href="5-rcd.html">rcd</a></li><li class="progresschapter"><a href="6-rls.html">6</a></li><li class="progresschapter"><a href="7-tc.html">7</a></li><li class="progresschapter"><a href="8-kpr.html">8</a></li><li class="progressnext"><a href="5-rf.html">&#10095;</a></li></ul></div>
</nav><!-- End of weave -->

		</main>
	</body>
</html>

